package com.alkaid.anime.filter;

import com.alkaid.commons.msg.MsgDefinition;
import com.alkaid.commons.entity.Authority;
import com.alkaid.commons.entity.User;
import com.alkaid.commons.ex.TokenErrorException;
import com.alkaid.commons.ex.TokenExpiredException;
import com.alkaid.commons.ex.TokenRefreshException;
import com.alkaid.commons.utils.JsonResult;
import com.alkaid.commons.utils.JwtUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * Token鉴权拦截器
 *
 * @author Kylin
 */
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    /**
     * Instantiates a new Jwt authorization filter.
     *
     * @param authenticationManager the authentication manager
     */
    public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        String tokenHeader = request.getHeader(JwtUtils.TOKEN_HEADER);
        // 如果请求头中没有Authorization信息则直接放行了
        if (tokenHeader == null || !tokenHeader.startsWith(JwtUtils.TOKEN_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        JwtUtils jwtUtils = new JwtUtils();
        try {
            boolean isFresh = jwtUtils.parseJwt(tokenHeader);
            // 是否需要更新token
            if (isFresh) {
                User user = jwtUtils.getUser();
                // 重新签发jwt
                String token = jwtUtils.createJwt(user, true);
                JwtUtils.responseStatus(response, new JsonResult<>(204, token, MsgDefinition.REFRESH_TOKEN));
                throw new TokenRefreshException("更新token");
            }
        } catch (TokenExpiredException e) {
            JwtUtils.responseStatus(response, new JsonResult<>(203, null, MsgDefinition.LOGIN_EXPIRED));
            return;
        } catch (TokenErrorException e) {
            JwtUtils.responseStatus(response, new JsonResult<>(203, null, MsgDefinition.LOGIN_EXCEPTION));
            return;
        } catch (Exception e) {
            JwtUtils.responseStatus(response, new JsonResult<>(800, null, "JwtAuthorizationFilter异常"));
            return;
        }
        String username = jwtUtils.getUser().getUsername();
        List<Authority> authorities = jwtUtils.getUser().getAuthorities();
        UsernamePasswordAuthenticationToken authenticationToken = null;
        if (username != null) {
            authenticationToken = new UsernamePasswordAuthenticationToken(username, null,
                    AuthorityUtils.commaSeparatedStringToAuthorityList(JwtUtils.parseAuthorities(authorities))
            );
        }
        // 如果请求头中有token，则进行解析，并且设置认证信息
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        super.doFilterInternal(request, response, chain);
    }
}
